//
//  main.cpp
//  opencv finish
//
//  Created by 杨经纬 on 2021/11/10.
//

#include <iostream>
#include <math.h>
#include <string>
#include <vector>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include "FrameProcessor.hpp"
#include "videoprocessor.hpp"


using namespace cv;
using namespace std;

Mat imgGray;
Mat drawing;
Mat try01;
Mat draw ;
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
vector<RotatedRect> minRect( contours.size() );
 vector<RotatedRect> minEllipse( contours.size() );


class CAB{
public:
    Point2f rect_points[4];
};

CAB QSD[15];

//vector<RotatedRect> minRect( contours.size() );

void Image_Gray(Mat);
void Outline(Mat);
void Armor_plate(Mat& img);
void processFrame(cv::Mat& img, cv::Mat& out);


// 对视频的每帧做Canny算子边缘检测
void canny(cv::Mat& img, cv::Mat& out)
{
    
    Image_Gray(img);
    Outline(imgGray);
    Armor_plate(img);
    out = draw;
    
}
int main(){
//    Mat img;
//    VideoCapture capture("Video.mp4");
//    double rate = capture.get(CAP_PROP_FPS);
//    bool stop(false);
//    Mat frame; // 当前视频帧
//    namedWindow("Extracted Frame");
//
//        // 每一帧之间的延迟
//    int delay= 1000/rate;
//    while (!stop)
//        {
//            Image_Gray(frame);
//            Outline(imgGray);
//            Armor_plate();
//            // 尝试读取下一帧
//            if (!capture.read(frame))
//                break;
//            //cv::imshow("Extracted Frame",frame);
//            // 引入延迟
//            if (cv::waitKey(delay)>=0)
//                    stop= true;
//        }
    // 定义一个视频处理类处理视频帧
    // 首先创建实例
    VideoProcessor processor;
    // 打开视频文件
    processor.setInput("Video.mp4");
    // 声明显示窗口
    // 分别为输入和输出视频
    processor.displayInput("Input Video");
    processor.displayOutput("Output Video");
    // 以原始帧率播放视频
    processor.setDelay(1000./processor.getFrameRate());
    // 设置处理回调函数
    processor.setFrameProcessor(canny);
    // 开始帧处理过程
    processor.run();
//    cv::waitKey();
//    img = imread("car.png");
//    Image_Gray(img);
//    imshow("Original drawing",img);
//    imshow("Grayscale image", imgGray);
//    Outline(imgGray);
//    Armor_plate();
    waitKey(0);
    return 0;
}

void Image_Gray(Mat img){
    Mat imgcolor;
    Mat Binarization;
    vector<Mat> counters;
    split(img, counters);
    imgcolor = counters.at(0)*1.0+counters.at(2)*1.0;              // - counters.at(2)*0.4;
    threshold(imgcolor, Binarization, 160, 255, THRESH_BINARY);
    Mat kernel = getStructuringElement(MORPH_RECT, Size(3,3));
    medianBlur(Binarization, imgGray, 3);
//    dilate(Binarization, Binarization, kernel);
//    erode(Binarization, imgGray, kernel);
}

void Outline(Mat imgGray){
    findContours(imgGray, contours, hierarchy,RETR_LIST, CHAIN_APPROX_NONE);
    vector<RotatedRect> minRect( contours.size() );
     vector<RotatedRect> minEllipse( contours.size() );
    
    
     for( int i = 0; i < contours.size(); i++ )
        { minRect[i] = minAreaRect( Mat(contours[i]) );
//          if( contours[i].size() > 5 )
//            { minEllipse[i] = fitEllipse( Mat(contours[i]) ); }
        }
    
     /// 绘出轮廓及其可倾斜的边界框和边界椭圆
    drawing = Mat::zeros( imgGray.size(), CV_8UC3 );
     for( int i = 0; i< minRect.size(); i++ )
        {
          //Scalar color = Scalar( imgGray.uniform(0, 255), imgGray.uniform(0,255), imgGray.uniform(0,255) );
          // contour
     //     drawContours( drawing, contours, i, Scalar(255,255,255), 1, 8, vector<Vec4i>(), 0, Point() );
          // ellipse
    //      ellipse( drawing, minEllipse[i], Scalar(255,255,255), 2, 8 );
          // rotated rectangle
            if(minRect[i].angle<20&&minRect[i].size.width/minRect[i].size.height<1.0){
           minRect[i].points( QSD[i].rect_points );
          for( int j = 0; j < 4; j++ )
             line( drawing, QSD[i].rect_points[j], QSD[i].rect_points[(j+1)%4], Scalar(255,255,255), 1, 8 );
            }
            if(minRect[i].angle>70&&minRect[i].size.width/minRect[i].size.height>1.0){
                 minRect[i].points( QSD[i].rect_points );
                Point2f A = QSD[i].rect_points[0];
                QSD[i].rect_points[0] = QSD[i].rect_points[3];
                QSD[i].rect_points[3] = QSD[i].rect_points[2];
                QSD[i].rect_points[2] = QSD[i].rect_points[1];
                QSD[i].rect_points[1] = A;
                for( int j = 0; j < 4; j++ )
                   line( drawing,QSD[i].rect_points[j], QSD[i].rect_points[(j+1)%4], Scalar(255,255,255), 1, 8 );
            }
        }
    
    
     /// 结果在窗体中显示
//    namedWindow( "Contours", WINDOW_AUTOSIZE );
//    imshow( "Contours", drawing );
}

void Armor_plate(Mat& img){
    draw = img;
    for(int i = 0;i< contours.size()-1;i++){
        for(int j = i;j < contours.size();j++){
            if(QSD[i].rect_points[0].y-QSD[j].rect_points[0].y<25&&QSD[i].rect_points[1].y-QSD[j].rect_points[1].y<25&&QSD[j].rect_points[0].y-QSD[i].rect_points[0].y<25&&QSD[j].rect_points[1].y-QSD[i].rect_points[1].y<25){
                
                if((QSD[j].rect_points[0].x-QSD[i].rect_points[0].x)/(QSD[i].rect_points[1].y-QSD[i].rect_points[0].y)<3&&(QSD[j].rect_points[0].x-QSD[i].rect_points[0].x)/(QSD[i].rect_points[1].y-QSD[i].rect_points[0].y)>2){
                    line(draw, QSD[i].rect_points[0], QSD[i].rect_points[1], Scalar(255,255,255), 1, 8);
                    line(draw, QSD[j].rect_points[0], QSD[j].rect_points[1], Scalar(255,255,255), 1, 8);
                    line(draw, QSD[i].rect_points[1],QSD[j].rect_points[1], Scalar(255,255,255), 1, 8);
                    line(draw, QSD[i].rect_points[0], QSD[j].rect_points[0], Scalar(255,255,255), 1, 8);
                }

            }
        }
    }
    
}
